package com.qiange.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiange.common.Result;
import com.qiange.dto.DishDto;
import com.qiange.exception.CustomException;
import com.qiange.pojo.Category;
import com.qiange.pojo.Dish;
import com.qiange.pojo.DishFlavor;
import com.qiange.pojo.SetmealDish;
import com.qiange.service.CategoryService;
import com.qiange.service.DishFlavorService;
import com.qiange.service.DishService;
import com.qiange.service.SetmealDishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
    @Autowired
    private DishService dishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 分页查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public Result<Page> selectByPage(int page, int pageSize, String name) {
        Page<Dish> dishPage = new Page<>(page, pageSize);
        Page<DishDto> dishDtoPage = new Page<>();


        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper();
        lqw.like(name != null, Dish::getName, name);
        lqw.orderByDesc(Dish::getUpdateTime);

        dishService.page(dishPage, lqw);

        BeanUtils.copyProperties(dishPage, dishDtoPage, "records");

        List<Dish> records = dishPage.getRecords();

        //遍历records
        List<DishDto> dishDtoList = records.stream().map((item) -> {

            //新建dio对象用来接收添加分类名称后的对象
            DishDto dishDto = new DishDto();

            //将对象中已有的菜品属性信息赋值给dishDto
            BeanUtils.copyProperties(item, dishDto);


            //取到每一个菜品得id，并通过id查找出对应得分类名,然后赋值给dishDto
            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);
            dishDto.setCategoryName(category.getName());

            //返回接收增加分类名后的dto对象，并进行下一组的遍历
            //当所有对象都遍历增加完后，进行收集然后赋给一个新的DishDto集合，并将DishDto集合的新数据替换掉原dishDtoPage中的records集合旧数据
            return dishDto;
        }).collect(Collectors.toList());

        //将赋值完分类名的集合赋值给dishDtoPage的集合属性，用来展示再页面
        dishDtoPage.setRecords(dishDtoList);

        return Result.success(dishDtoPage);
    }

    /**
     * 添加菜品
     *
     * @param dishDto
     * @return
     * CacheEvict添加菜品后删除缓存，让移动端的用户能够实时查看最新数据
     */
    @CacheEvict(value = "dish:list",allEntries = true)
    @PostMapping
    public Result<String> add(@RequestBody DishDto dishDto) {
//        System.out.println(dishDto);

        log.info(dishDto.toString());
        dishService.saveWithFlavor(dishDto);

        /*        //删除缓存中的所有分类
        Set keys = redisTemplate.keys("dishId*");
        redisTemplate.delete(keys);*/


        //根据分类id动态构造key
        String key = "dishId_" + dishDto.getCategoryId() + "_1";

        //清楚缓存，为了保持缓存中的数据与数据库中修改后的数据一致
        redisTemplate.delete(key);

        return Result.success("增加菜品成功");
    }

    /**
     * 根据id查找菜品
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<DishDto> selectById(@PathVariable Long id) {

        DishDto dishDto = dishService.getByIdWithFlavor(id);


        return Result.success(dishDto);
    }

    /**
     * 修改菜品信息
     * @param dishDto
     * @return
     * CacheEvict修改菜品后删除缓存，让移动端的用户能够实时查看最新数据
     */
    @CacheEvict(value = "dish:list",key = "#dishDto.categoryId")
    @PutMapping
    public Result<String> update(@RequestBody DishDto dishDto) {
//        System.out.println(dishDto);

        log.info(dishDto.toString());
        dishService.updateWithFlavor(dishDto);

/*        //删除缓存中的所有分类
        Set keys = redisTemplate.keys("dishId*");
        redisTemplate.delete(keys);*/


        //根据分类id动态构造key
//        String key = "dishId_" + dishDto.getCategoryId() + "_1";

        //清楚缓存，为了保持缓存中的数据与数据库中修改后的数据一致
//        redisTemplate.delete(key);

        return Result.success("修改菜品成功");
    }

    /**
     * 删除/批量删除菜品信息
     * @param ids
     * @return
     * CacheEvict删除菜品后删除缓存，让移动端的用户能够实时查看最新数据
     */
    @CacheEvict(value = "dish:list",allEntries = true)
    @DeleteMapping
    public Result<String> deleteByIds(@RequestParam List<Long> ids) {

        log.info(ids.toString());

        LambdaQueryWrapper<Dish> dishLqw = new LambdaQueryWrapper();
        dishLqw.in(Dish::getId, ids);
        dishLqw.eq(Dish::getStatus, 1);
        int count = dishService.count(dishLqw);

        if (count > 0) {
            throw new CustomException("无法删除在售的菜品");
        }

        dishService.removeByIds(ids);

        LambdaQueryWrapper<DishFlavor> lqw = new LambdaQueryWrapper();


//        for (Long id : ids) {
//            lqw.eq(DishFlavor::getDishId,id);
//            dishFlavorService.remove(lqw);
//        }

        lqw.in(DishFlavor::getDishId, ids);
        dishFlavorService.remove(lqw);

        //删除缓存中的所有分类
        Set keys = redisTemplate.keys("dishId*");
        redisTemplate.delete(keys);


        return Result.success("删除成功");
    }

    /**
     * 修改菜品在售状态
     * @param status
     * @param ids
     * @return
     * CacheEvict修改菜品后删除缓存，让移动端的用户能够实时查看最新数据
     */
    @CacheEvict(value = "dish:list",allEntries = true)
    @PostMapping("/status/{status}")
    public Result<String> updateStatus(@PathVariable Integer status, @RequestParam List<Long> ids) {

//        List<Dish> dishList = new ArrayList<>();
//
//        for (Long id : ids) {
//            Dish dish = new Dish();
//            dish.setStatus(status);
//            dish.setId(id);
//
//            dishList.add(dish);
//        }
//
//        dishService.updateBatchById(dishList);

        LambdaQueryWrapper<SetmealDish> QueryWrapper = new LambdaQueryWrapper<>();
        QueryWrapper.in(SetmealDish::getDishId, ids);
        int count = setmealDishService.count(QueryWrapper);
        if (count > 0) {
            throw new CustomException("有套餐在使用该菜品，无法停售");
        }


        LambdaUpdateWrapper<Dish> lqw = new LambdaUpdateWrapper<>();
        lqw.in(Dish::getId, ids);
        lqw.set(Dish::getStatus, status);

        dishService.update(lqw);

        //删除缓存中的所有分类
//        Set keys = redisTemplate.keys("dishId*");
//        redisTemplate.delete(keys);

        return Result.success("停售成功");
    }

//    @GetMapping("/list")
//    public Result<List<Dish>> getList(Dish dish){
//
//
//        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper();
//        lqw.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
//        lqw.eq(Dish::getStatus,1);
//        lqw.orderByDesc(Dish::getUpdateTime);
//
//        List<Dish> dishList = dishService.list(lqw);
//
//
//        return Result.success(dishList);
//    }


    /**
     * 根据分类id查找菜品信息及口味信息
     *
     * @param dish
     * @return
     *利用Cacheable实现菜品的缓存功能，替代原来的redisTemplate实现
     * Cacheable会判断当前缓存的key是否有数据，如果没有数据，就将返回值存入缓存
     * unless = "#result.data == null 如果result.data的值为空的话就不加入缓存
     */
    @Cacheable(value = "dish:list",key = "#dish.categoryId",unless = "#result.data == null")
    @GetMapping("/list")
    public Result<List<DishDto>> getList(Dish dish) {

        List<DishDto> dishDtoList = null;

        //根据分类id动态构造Key

//        String key = "dishId_" + dish.getCategoryId() + "_" + dish.getStatus();

        //先根据选中的分类ID取出缓存中的数据
//        dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);

        //判断是否有数据，如果有直接返回，没有的话执行数据库查询,并把查出的数据存入redis缓存

        if (dishDtoList != null) {
            return Result.success(dishDtoList);
        }

        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper();
        lqw.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
        lqw.eq(dish.getStatus() != null, Dish::getStatus, 1);
        lqw.orderByDesc(Dish::getUpdateTime);

        List<Dish> dishList = dishService.list(lqw);

        dishDtoList = dishList.stream().map((item) -> {
            DishDto dishDto = new DishDto();

            BeanUtils.copyProperties(item, dishDto);

            Category category = categoryService.getById(item.getCategoryId());

            dishDto.setCategoryName(category.getName());

            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId, item.getId());

            List<DishFlavor> dishFlavorList = dishFlavorService.list(dishFlavorLambdaQueryWrapper);

            dishDto.setFlavors(dishFlavorList);

            return dishDto;

        }).collect(Collectors.toList());



//        redisTemplate.opsForValue().set(key, dishDtoList, 60, TimeUnit.MINUTES);

        return Result.success(dishDtoList);
    }
}
